package gateway

import (
	"github.com/smallnest/rpcx/protocol"
	"gogame/gameservice"
	"gogame/gameservice/service"
	"gogame/lib"
	"sync"
	"time"
)

type Sender struct {
	uid2Conn *sync.Map
	service  service.IService
}

func NewSender(service service.IService) *Sender {
	return &Sender{
		uid2Conn: new(sync.Map),
		service:  service,
	}
}

// RegisterFunc 处理rpcXServer推送过来的消息
func (s *Sender) RegisterFunc(serviceName string) name2Func {
	switch serviceName {
	case "api":
		return name2Func{
			"SendMsgByUid":       s.SendMsgByUid,
			"SendMsgByAll":       s.SendMsgByAll,
			"OtherLogin":         s.OtherLogin,
			"NoticeSaveUserData": s.NoticeSaveUserData,
			"SendCrossMsg":       s.SendCrossMsg,
			"StopTimer":          s.StopTimer,
			"StopModelLog":       s.StopModelLog,
		}
	default:
		return nil
	}
}

// Stop 关闭所有链接
func (s *Sender) Stop() {
	s.uid2Conn.Range(func(uid, conn any) bool {
		conn.(*GatewayApp).OnClose()
		return true
	})
}

// SetUser 设置玩家uid对应的链接对象
func (s *Sender) SetUser(conn *GatewayApp) {
	s.uid2Conn.Store(conn.Uid, conn)
}

// DelUser 移除玩家uid对应的链接对象
func (s *Sender) DelUser(conn *GatewayApp) {
	_fConn := s.GetUidConn(conn.Uid)
	// 玩家不在线
	if _fConn == nil {
		return
	}

	// 登陆时间不一致
	if _fConn.LoginTime != conn.LoginTime {
		return
	}

	s.uid2Conn.Delete(conn.Uid)
}

// GetUidConn 获取玩家gatewayApp
func (s *Sender) GetUidConn(uid string) *GatewayApp {
	_gatewayApp, ok := s.uid2Conn.Load(uid)
	// 玩家不在线
	if !ok {
		return nil
	}

	return _gatewayApp.(*GatewayApp)
}

// OtherLogin 其他玩家登陆
func (s *Sender) OtherLogin(msg *protocol.Message) {
	uid, ok := msg.Metadata["uid"]
	// 必须要传uid
	if !ok {
		return
	}

	_gatewayApp := s.GetUidConn(uid)
	// 玩家不在线
	if _gatewayApp == nil {
		return
	}
	_gatewayApp.OtherLoginGatewayUrl = msg.Metadata["othergateway"]
	_gatewayApp.ResponseAny(map[string]any{"s": -88, "errmsg": "账号在其他地方登陆"})
	time.Sleep(time.Millisecond * 100)
	_gatewayApp.OnClose()
}

// SendMsgByUid 发送消息到指定uid
func (s *Sender) SendMsgByUid(msg *protocol.Message) {
	uid, ok := msg.Metadata["uid"]
	// 必须要传uid
	if !ok {
		return
	}

	_gatewayApp := s.GetUidConn(uid)
	// 玩家不在线
	if _gatewayApp == nil {
		return
	}

	var _msg any
	_ = lib.Loads(msg.Payload, &_msg)
	_gatewayApp.Response(_msg, "")
}

// SendMsgByAll 发送消息给所有玩家
func (s *Sender) SendMsgByAll(msg *protocol.Message) {
	var _msg any
	_ = lib.Loads(msg.Payload, &_msg)
	s.uid2Conn.Range(
		func(key, value any) bool {
			value.(*GatewayApp).Response(_msg, "")
			return true
		},
	)
}

// NoticeSaveUserData 通知保存玩家数据
func (s *Sender) NoticeSaveUserData(msg *protocol.Message) {
	uid, ok := msg.Metadata["uid"]
	// 必须要传uid
	if !ok {
		return
	}

	s.service.Notice(s.service, "NoticeSaveUserData", uid)

}

// SendCrossMsg 发送跨服消息
func (s *Sender) SendCrossMsg(msg *protocol.Message) {
	_service := s.service.(*Service)
	_client := _service.RpcManage.GetRpcXClient("cross_api")
	var _msg any
	_ = lib.Loads(msg.Payload, &_msg)
	_client.Notice("SendCrossMsg", _msg)

}

// StopTimer 停止定时器
func (s *Sender) StopTimer(msg *protocol.Message) {
	gameservice.StopService("timer", s.service.GetListen())

}

// StopModelLog 停止数据写入
func (s *Sender) StopModelLog(msg *protocol.Message) {
	gameservice.StopService("modellog", s.service.GetListen())
}
